package com.example.demo.encode;

import java.util.Random;

public class Test {

    private static void byteBasedCipherTest() {
        int i;
        int dataLen;
        int encodeLen;
        byte[] in;
        byte decode[];
        byte out[]; // 128
        long startEncodeTime;
        byte[] dynKey = new byte[32];
        byte keyValue[] = {
            (byte) 0xa4, (byte) 0x3e, (byte) 0xd2, (byte) 0xca,
            (byte) 0x71, (byte) 0xce, (byte) 0xd2, (byte) 0x41,
            (byte) 0xa3, (byte) 0xa9, (byte) 0xe8, (byte) 0x33,
            (byte) 0x02, (byte) 0xd9, (byte) 0xdb, (byte) 0xf0,
            (byte) 0xcf, (byte) 0xaf, (byte) 0xde, (byte) 0xc6,
            (byte) 0x6d, (byte) 0x7a, (byte) 0x6a, (byte) 0x07,
            (byte) 0x40, (byte) 0xc5, (byte) 0x45, (byte) 0xf4,
            (byte) 0xb9, (byte) 0xb4, (byte) 0x8f, (byte) 0xb8};
        byte saltData[] = {
            (byte) 0xa4, (byte) 0x3e, (byte) 0xd2, (byte) 0xca,
            (byte) 0x71, (byte) 0xce, (byte) 0xd2, (byte) 0x41,
            (byte) 0xa3, (byte) 0xa9, (byte) 0xe8, (byte) 0x33,
            (byte) 0x02, (byte) 0xd9, (byte) 0xdb, (byte) 0xf0,
        };


        AesKeyExpand keyExpand = new AesKeyExpand(keyValue, saltData);
        AesCipher cipher = new AesCipher(keyExpand);

//		while(true)
        {
            for (i = 0; i < 32; i++) {
                dynKey[i] = (byte) (Math.random() * 256);
            }
            dataLen = 31;//((int) (Math.random() * 1024 * 1024 * 10));
            encodeLen = dataLen;
            if ((dataLen % 16) != 0) {
                encodeLen = ((dataLen / 16) + 1) * 16;
            }
            in = new byte[dataLen];
            out = new byte[encodeLen]; // 128
            decode = new byte[dataLen];
            for (i = 0; i < dataLen; i++) {
                in[i] = (byte) i;//(byte)(Math.random() * 256);
            }
            System.out.printf("\ninput :\n");
            for (i = 0; i < dataLen; i++) {
                if ((in[i] & 0xf0) == 0) {
                    System.out.printf("0");
                }
                System.out.printf("%x, ", in[i]);
            }

            /* 加密  传入数据长度，如果数据不为16字节的整数倍，则自动向后补0，直到16的整数倍。 */
            startEncodeTime = System.currentTimeMillis();
            cipher.encodeData(in, out, dataLen, keyExpand);
            long endEncodeTime = System.currentTimeMillis();

            System.out.printf("\n out:\n");
            for (i = 0; i < encodeLen; i++) {
                if ((out[i] & 0xf0) == 0) {
                    System.out.printf("0");
                }
                System.out.printf("%x, ", out[i]);
            }
            System.out.printf("\n");

            /* 解密  dataLen 指原始数据的长度 decode的长度可能>= datalen */
            long startDecodeTime = System.currentTimeMillis();
            cipher.decodeData(out, decode, dataLen, keyExpand);
            long endDecodeTime = System.currentTimeMillis();

            System.out.printf("\n msg :\n");
            for (i = 0; i < dataLen; i++) {
                if ((decode[i] & 0xf0) == 0) {
                    System.out.printf("0");
                }
                System.out.printf("%x, ", decode[i]);
            }
            boolean isSame = true;

            for (i = 0; i < dataLen; i++) {
                if (decode[i] != in[i]) {
                    isSame = false;
                    System.out.printf("\r\n\r\nerror!!!!!!!!!!!!!!!!!!!!!!!!!!!! %d %d %d \r\n\r\n", i, decode[i],
                        in[i]);
                    try {
                        Thread.sleep(1000 * 60 * 60);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }

            if (isSame == true) {
                System.out.printf("\n<<<<----success----dataLen=%d----encodeTime=%d, decodeTime=%d>>>>\n",
                    dataLen, endEncodeTime - startEncodeTime, endDecodeTime - startDecodeTime);
            }
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    volatile static byte s_box[][] = new byte[16][16];
    volatile static byte itv_s_box[][] = new byte[16][16];

    private static boolean checkIsHasSame(int i, int j) {
        int m, n = j;
        for (m = i; m >= 0; m--) {
            for (n = 15; n >= 0; n--) {
                if (m == i && n == j) {
                    continue;
                }
                if (s_box[i][j] == s_box[m][n]) {
                    return true;
                }
            }
        }

        return false;

    }

    private static void generalMatrixFunction() {
        int i, j, row, col;

        System.out.print("s_box = [");
        for (i = 0; i < 16; i++) {
            System.out.print("\r\n");
            for (j = 0; j < 16; j++) {
                s_box[i][j] = (byte) (Math.random() * 256);
                while (true == checkIsHasSame(i, j)) {
                    s_box[i][j] = (byte) (Math.random() * 256);
                }
                System.out.print("0x");

                if ((s_box[i][j] & 0xf0) == 0) {
                    System.out.print("0");
                }
                System.out.printf("%x, ", (byte) s_box[i][j]);
            }
        }
        System.out.printf("] \r\n");

        for (i = 0; i < 16; i++) {
            for (j = 0; j < 16; j++) {
                row = (s_box[i][j] & 0xf0) / 16;
                col = s_box[i][j] & 0x0f;
                itv_s_box[row][col] = (byte) (i * 16 + j);
            }
        }

        System.out.print("itv_s_box = [");
        for (i = 0; i < 16; i++) {
            System.out.print("\r\n");
            for (j = 0; j < 16; j++) {
                System.out.print("0x");
                if ((itv_s_box[i][j] & 0xf0) == 0) {
                    System.out.print("0");
                }
                System.out.printf("%x, ", itv_s_box[i][j]);
            }
        }
    }


    private static boolean checkResult(String src, String dst) {
        boolean isSame = true;
        if (!src.equals(dst)) {
            isSame = false;
            System.out.println("differ with each other!!");
        } else {
            System.out.println("Same with each other!!");
        }

        return isSame;
    }

    private static final String SOURCES = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";

    private static String getRandomString(int length) {
        Random random = new Random();
        char[] text = new char[length];
        for (int i = 0; i < length; i++) {
            text[i] = SOURCES.charAt(random.nextInt(SOURCES.length()));
        }
        return new String(text);
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        /*AesCipher cipher = new AesCipher("1");

        String orgStr = getRandomString((int) 133);
        System.out.println("OriginalString:\n" + orgStr);

        String enCodeStr = cipher.encodeStr(orgStr);
        System.out.println("EncodeString:\n" + enCodeStr);

        String deCodeStr = cipher.decodeStr(enCodeStr);
        System.out.println("DecodeString:\n" + deCodeStr);

        checkResult(orgStr, deCodeStr);*/


        AesCipherUtil util = new AesCipherUtil();

        String json =
            "rU5NdiZejQuyTNF4kBvXS1uCmFVWoL39TUT2H9XB4FxWTAIpyFrr4xLeLP7VOwkL5sEz7ViEbkAji9tk3gCcH40XhIF8utsWpXcnhJwXy3cP0hN4jMCA394PYQBLqIcrFsYECYVpHNEvr02UUsrUMoRXdLXZDL3wyYTChcqzisgnEA9jCgz7kNQqnJDn4qDYz3ZhbR7xYrI0kQa5TwjVWrGJ1Z0MedUQX6j5VGRZs025pB1firwGY2Hoz377Ol8";

        //AES加密参数
//        for (int i = 0; i < 10; i++) {
//            AesCipher encode = new AesCipher(AesCipher.HANDLE_TYPE_RANDOM_KEY_ENCODE, util);
//            String enCodeStr2 = encode.encodeStr(json);
//            System.out.println("EncodeString:\n" + enCodeStr2);
//
//            //随机解密操作
//            AesCipher decode = new AesCipher(AesCipher.HANDLE_TYPE_RANDOM_KEY_DECODE, util);
//            String deCodeStr2 = decode.decodeStr(enCodeStr2);
//            System.out.println("DecodeString:\n" + deCodeStr2);
//
//            System.out.println("compare:" + deCodeStr2.equals(json));
//        }

        String test = "AAAAAQAAAA#qulWguoXQ94krZepa6lnQ";

        //随机解密操作
        for (int i =0; i<1;i++) {
            AesCipher decode = new AesCipher(AesCipher.HANDLE_TYPE_RANDOM_KEY_DECODE, util);
            String deCodeTest = decode.decodeStr(test);
            System.out.println("DecodeString:\n" + deCodeTest);
        }

    }

}
